﻿using Dapper.DBContext;
using Guoc.BigMall.Domain.Entity;
using Guoc.BigMall.Domain.Service;
using Guoc.BigMall.Domain.ValueObject;
using Guoc.BigMall.Infrastructure;
using Guoc.BigMall.Infrastructure.Extension;
using Guoc.BigMall.Infrastructure.Payment;
using Guoc.BigMall.Infrastructure.Payment.Wechat;
using Guoc.BigMall.Infrastructure.Utils;
using Guoc.BigMall.Infrastructure.WeChat.JsSdk;
using Guoc.BigMall.WebService.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Guoc.BigMall.WebService.Implement
{
    public class SaleOrderService : ISaleOrderService
    {
        IUserContextService _userContext;
        IDBContext _db;
        ICodeSequenceService _sequence;
        IPayService _payService;
        IWechatService _wechatService;
        public SaleOrderService(IDBContext dbContext, IUserContextService userContext, ICodeSequenceService sequence, IPayService payService,
            IWechatService wechatService)
        {
            this._db = dbContext;
            _userContext = userContext;
            _sequence = sequence;
            _payService = payService;
            _wechatService = wechatService;

        }
        public int PlaceOrder(SaleOrderCreateDto model)
        {

            // order 下单幂等处理
            if (model.OrderId > 0 && _db.Table<SaleOrder>().Exists(n => n.Id == model.OrderId))
            {
                return model.OrderId;
            }
            if (model.Items.Count == 0)
            {
                throw new FriendlyException("订单明细为空");
            }
            // var order=  AutoMapper.Mapper.Map<SaleOrderCreateDto, SaleOrder>(model);
            var order = model.MapTo<SaleOrder>();
            // 创建新订单          
            order.MemberId = _userContext.Current.MemberId;
            order.Code = _sequence.NewCode(BillIdentity.SaleOrder, order.MemberId);
            var storeCode = _userContext.Current.StoreCode;
            var store = _db.Table<Store>().FirstOrDefault(n => n.Code == storeCode);
            order.StoreId = store.Id;
            // 有推荐会员，保存会员ID
            var referMember = _db.Table<Member>().FirstOrDefault(n => n.Id == model.ReferMemberId);
            order.ReferMemberId = referMember == null ? 0 : referMember.Id;
            // 订单明细
            var pidArray = model.Items.Select(n => n.ProductId).ToArray();
            var products = _db.Table<Product>().Where(n => n.Id.In(pidArray)).ToDictionary(n => n.Id);
            order.Items.Clear();
            foreach (var item in model.Items)
            {
                if (products.ContainsKey(item.ProductId) && item.Quantity > 0)
                {
                    var sku = products[item.ProductId];
                    var orderItem = new SaleOrderItem()
                    {
                        ProductId = sku.Id,
                        ProductCode = sku.Code,
                        ProductName = sku.ShowName,
                        Quantity = item.Quantity,
                        SalePrice = sku.SalePrice,
                        RealPrice = sku.SalePrice
                    };
                    order.Items.Add(orderItem);
                }
            }
            // 计算订单金额
            order.SumOrderAmount();

            //收货地址信息
            var mbrAddress = _db.Table<MemberAddress>().FirstOrDefault(n => n.Id == model.MemberAddressId);
            if (mbrAddress == null)
            {
                throw new FriendlyException("收货地址不能为空");
            }
            order.AddMemberAddress(mbrAddress);

            // 创建分销订单
            DistributeOrder entity = new DistributeOrder()
            {
                Code = _sequence.NewCode(BillIdentity.DistributeOrder, order.MemberId),
                MemberId = order.MemberId,
                NickName = _userContext.Current.NickName,
                MemberName = model.ContactName,
                MemberPhone = model.Phone,
                ContactPhone = model.ContactPhone,
                IdentityCard = model.IdentityCard,
                ReferMemberId = order.ReferMemberId,
                SaleOrderId = order.Id,
                SaleOrderCode = order.Code,
                StoreId = order.StoreId,
                StoreCode = store.Code
            };
            // 记录分销单历史
            DistributeOrderHistory history = new DistributeOrderHistory()
            {
                Createdby = 1,
                CreatedbyName = "系统",
                Remark = "创建分销订单",
                Status = entity.Status
            };
            entity.Historys.Add(history);
            _db.Insert(entity);


            _db.Insert(order);
            _db.SaveChange();
            return order.Id;

        }

        /// <summary>
        /// {"orderId":8,"paymentWay":1,"payUrl":"http://www.huijitong.top/","openId":"oF5LD1agEEXKfbNKq9f1jX29bMfc"}
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public JsPayResult ConfirmPay(PayOrderDto order)
        {
            var entity = _db.Table<SaleOrder>().FirstOrDefault(n => n.Id == order.OrderId);
            if (entity == null)
            {
                throw new FriendlyException("支付单 不存在");
            }
            if (entity.Status != Domain.ValueObject.SaleOrderStatus.WaitToPay)
            {
                throw new FriendlyException("请勿重复支付");
            }
            System.Threading.Thread.Sleep(3000);
            // 计算订单支付金额
            var entityItems = _db.Table<SaleOrderItem>().Where(n => n.SaleOrderId == order.OrderId).ToList();
            if (entityItems.Count == 0) { throw new FriendlyException("支付单明细为空"); }
            entity.Items = entityItems;

            // 发起统一支付接口
            var store = _db.Table<Store>().FirstOrDefault(n => n.Id == entity.StoreId);
            var wxPay = _payService.GetPayGetway<WechatGetway>(store.Code);
            PayRequest payreq = new PayRequest();
            payreq.Add("openid", order.OpenId);
            payreq.Add("out_trade_no", entity.Code);
            payreq.Add("total_fee", Decimal.ToInt32(entity.OrderAmount * 100));  // int.Parse(entity.OrderAmount*100));
            payreq.Add("body", entity.Items.First().ProductName);
            payreq.Add("trade_type", "JSAPI");
            payreq.Add("spbill_create_ip", order.IpAddress); //终端ip
            var payResult = wxPay.UnifiedOrder(payreq);

            // 根据统一支付接口，组装jsapi 参数
            var jsPayResult = (JsPayResult)_wechatService.BuildJsSdkConfig(order.PayUrl, store.Code);

            jsPayResult.package = "prepay_id=" + payResult.GetValue("prepay_id");
            // jsPayResult.paySign = payResult.GetValue("sign").ToString();
            //构建js 支付签名
            PayResult jsResult = new PayResult();
            jsResult.Add("appId", jsPayResult.appId);
            jsResult.Add("timeStamp", jsPayResult.timestamp);
            jsResult.Add("nonceStr", jsPayResult.nonceStr);
            jsResult.Add("package", jsPayResult.package);
            jsResult.Add("signType", AbstractRequest.SIGN_TYPE_MD5); //签名方式，与统一下单保持一致
            var paySign = jsResult.MakeSign(AbstractRequest.SIGN_TYPE_MD5, wxPay.Config.MchKey);

            jsPayResult.paySign = paySign;
            jsPayResult.signType = AbstractRequest.SIGN_TYPE_MD5;


            //记录统一下单交易记录
            TransactionHistory histroy = new TransactionHistory()
            {
                TradeType = TradeType.OrderPay,
                TradeKey = TradeKeyName.Wechat_Untified_Trade,
                TradeName = "微信统一下单",
                TradeCode = entity.Code,
                TradeAmount = entity.OrderAmount,
                TradeContent = payreq.ToXml(),
                TradeDate = DateTime.Now
            };
            _db.Insert(histroy);
            _db.SaveChange();


            return jsPayResult;

        }

        public void PaidNotify()
        {
            throw new NotImplementedException();
        }

        public SaleOrderVo GetOrderDetail(int orderId)
        {
            var entity = _db.Table<SaleOrder>().FirstOrDefault(so => so.Id == orderId);
            if (entity == null)
            {
                throw new FriendlyException("订单不存在");
            }
            var sql = @"select i.*,p.ImageUrl
from  SaleOrderItem i inner join productpicture p on p.ProductId=i.ProductId 
where i.SaleOrderId =  @OrderId ";

            var orderItemListVo = _db.DataBase.Query<SaleOrderItemVo>(sql, new { OrderId = orderId }).ToList();

            SaleOrderVo order = new SaleOrderVo()
            {
                Id = orderId,
                Code = entity.Code,
                CreatedOn = entity.CreatedOn,
                Status = entity.Status,
                Items = orderItemListVo
            };

            return order;
        }
        /// <summary>
        /// 获取订购商品列表
        /// </summary>
        /// <param name="productIdAndQuantityList">格式：pid-qty,pid2-qty2,pid3-qty3</param>
        /// <returns></returns>
        public OrderProductVo GetOrderProduct(string productIdAndQuantityList)
        {
            if (string.IsNullOrEmpty(productIdAndQuantityList))
            {
                throw new FriendlyException("订单商品为空");
            }
            // 转换格式 
            var productIdAndQuantityArray = productIdAndQuantityList.Split(',');
            Dictionary<int, int> productIdAndQuantityDic = new Dictionary<int, int>();
            foreach (var line in productIdAndQuantityArray)
            {
                var pidAndQtyPairs = line.Split('-');
                if (pidAndQtyPairs.Length < 2) { throw new FriendlyException("商品id,数量格式错误.应为:pid-qty"); }
                var pid = 0;
                var qty = 0;
                if (!int.TryParse(pidAndQtyPairs[0], out pid))
                {
                    throw new FriendlyException("商品id格式错误");
                }
                if (!int.TryParse(pidAndQtyPairs[1], out qty))
                {
                    throw new FriendlyException("数量格式错误");
                }
                if (!productIdAndQuantityDic.ContainsKey(pid))
                {
                    productIdAndQuantityDic.Add(pid, qty);
                }
            }
            var idArray = productIdAndQuantityDic.Keys.ToArray();
            // 查询商品
            var sql = @"select p.Id as ProductId,p.code as ProductCode,p.ShowName,p.SalePrice,pp.ImageUrl 
from Product p left join ProductPicture pp on p.Id=pp.ProductId where p.Id in @PIds";
            var orderItemListVo = _db.DataBase.Query<OrderProductItemVo>(sql, new { PIds = idArray }).ToList();
            foreach (var item in orderItemListVo)
            {
                if (productIdAndQuantityDic.ContainsKey(item.ProductId))
                {
                    item.Quantity = productIdAndQuantityDic[item.ProductId];
                }
            }
            var orderVo = new OrderProductVo();
            orderVo.Items = orderItemListVo;
            orderVo.SumTotalAmount();
            return orderVo;
        }
    }
}
